/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: 
 * 系统版本: 1.0.0
 * 开发人员: zhangfb
 * 开发时间: 2019/4/10 14:57
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.hyacinth.activity.service;

import com.hyacinth.activity.domain.ActDict;
import com.hyacinth.activity.entity.ActivityPlan;
import com.hyacinth.activity.entity.Award;
import com.hyacinth.activity.repository.PartiActRecordRepository;
import com.hyacinth.utils.DateUtils;
import com.hyacinth.utils.NumberUtils;
import com.hyacinth.utils.StringUtils;
import com.hyacinth.wapper.RetValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.util.StringJoiner;

/**
 * 参与活动记录服务层
 * @author zhangfb
 * @version 1.0.0.1
 * @since JDK 1.8
 */
@Service
@Transactional
public class PartiActRecordService {

    @Autowired
    private PartiActRecordRepository partiActRecordRepository;

    /**
     * 校验参与权限
     * @param plan     活动计划
     * @param userCode 用户编码
     * @return 校验结果
     */
    public RetValue checkPartiTimes(ActivityPlan plan, String userCode) {
        // 校验活动次数
        if (sumPartiActTimes(plan, userCode) >= plan.getPerPartiLimit()) {
            return RetValue.getErrorReturnValue("您参与本活动次数已达上限，请于下个活动周期再次参加");
        }
        return RetValue.getSuccessReturnValue();
    }

    /**
     * 汇总用户参与活动次数
     * @param plan 活动
     * @param userCode 用户编码
     * @return 活动次数
     */
    public long sumPartiActTimes(ActivityPlan plan, String userCode) {
        StringJoiner sql = new StringJoiner(packSqlByActAndUser(plan, userCode, null, true).toString());
        sql.add("SELECT COUNT(1) from (").add(") t");
        return partiActRecordRepository.querySQLForCount(sql.toString());
    }

    /**
     * 汇总用户获得奖励金额
     * @param plan 活动
     * @param userCode 用户编码
     * @return 活动次数
     */
    public BigDecimal sumPartiActAmt(ActivityPlan plan, String userCode) {
        StringJoiner sql = new StringJoiner(packSqlByActAndUser(plan, userCode, null, true).toString());
        sql.add("SELECT SUM(reward_amt) from (").add(") t");
        Object sumRes = partiActRecordRepository.sumWithSql(sql.toString());
        return sumRes == null ? BigDecimal.ZERO : new BigDecimal(sumRes.toString());
    }

    /**
     * 拼装SQL语句
     * @param actPlan 活动方案
     * @param userCode 用户编码
     * @param awardCode 奖品
     */
    private StringBuilder packSqlByActAndUser(ActivityPlan actPlan, String userCode, String awardCode, boolean isValid) {
        StringBuilder sql = new StringBuilder("SELECT * FROM hoyi_user_parti_act_record WHERE 1=1");

        //添加失效条件
        if (isValid) {
            sql.append(" AND is_valid='1'");
        } else {
            sql.append(" AND is_valid='0'");
        }
        // 添加用户条件
        if (StringUtils.isNotBlank(userCode)) {
            sql.append(" AND user_code='").append(userCode).append("'");
        }
        // 添加奖品条件
        if (StringUtils.isNotBlank(awardCode)) {
            sql.append(" AND award_code='").append(awardCode).append("'");
        }

        if (actPlan != null) {
            // 添加活动条件
            sql.append(" AND activity_code='").append(actPlan.getCode()).append("'");
            // 添加时间限制, 根据不同活动周期进行记录查询
            String actPeriod = actPlan.getPartiPeriod();
            if (ActDict.partiActPeriodType_01.equals(actPeriod)) {
                // 周期为每天
                sql.append(" AND DATE(parti_time) = DATE(NOW())");
            } else if (ActDict.partiActPeriodType_03.equals(actPeriod)) {
                // 周期为每月
                sql.append(" AND DATE_FORMAT(parti_time,'%Y-%m') = DATE_FORMAT(NOW(),'%Y-%m')");
            } else if (ActDict.partiActPeriodType_06.equals(actPeriod)) {
                // 周期为不限制
                String start = DateUtils.formatDateTime(actPlan.getBegTime());
                String end = DateUtils.formatDateTime(actPlan.getEndTime());
                sql.append(" AND parti_time >= '").append(start).append("'");
                sql.append(" AND parti_time <= '").append(end).append("'");
            }
        }
        return sql;
    }
}
